/* OCamlyacc parser for APost */
/* EMILY: flights to paderborn? */
%{
open Utils;;

let commands = Hashtbl.create 60;;

let regc id (f: int -> symbol) = Hashtbl.add commands id f;;

let getc x = 
    try 
        (Hashtbl.find commands (fst x)) (snd x) 
    with Not_found -> 
        raise (APostException [snd x]);;

regc "print" (fun l -> Print l);;
regc "printline" (fun l -> Printline l);;
regc "call" (fun l -> Call l);;
regc "set_dict" (fun l -> Set_dict l);;
regc "get_dict" (fun l -> Get_dict l);;
regc "new_dict" (fun l -> New_dict l);;
regc "has_dict" (fun l -> Has_dict l);;
regc "load" (fun l -> Load l);;
regc "store" (fun l -> Store l);;
regc "exception" (fun l -> Exception l);;
regc "push_env" (fun l -> Push_env l);;
regc "tostring" (fun l -> Tostring l);;
regc "new_list" (fun l -> New_list l);;
regc "head_list" (fun l -> Head_list l);;
regc "tail_list" (fun l -> Tail_list l);;
regc "get_list" (fun l -> Get_list l);;
regc "set_list" (fun l -> Set_list l);;
regc "branch" (fun l -> Branch l);;
regc "return" (fun l-> Return l);;
regc "loop" (fun l -> Loop l);;
regc "dup" (fun l ->Dup l);;
regc "none" (fun l -> NoneConst l);;
regc "discard" (fun l -> Discard l);;
regc "typeof" (fun l -> Typeof l);;
regc "stacksize" (fun l -> Stacksize l);;
regc "freeze" (fun l -> Freeze l);;
%}

%token <int * int> INTEGER
%token <string * int> STRING COMMAND
%token <int> ADD SUB MUL DIV MOD NONE
%token <int> LBRACE RBRACE LPAREN RPAREN
%token <int> EQ GT LT
%token <bool * int> BOOLEAN

%type <Utils.symbol> command
%start command

%%

commandlist:
    command                       { [$1] }
  | commandlist command           { $1 @ [$2] }
;
command:
    INTEGER                       { IntConst (fst $1, snd $1) }
  | STRING                        { StringConst (fst $1, snd $1) }
  | BOOLEAN                       { BoolConst (fst $1, snd $1) }
  | NONE                          { NoneConst $1}
  | ADD                           { Add $1 }
  | SUB                           { Sub $1 }
  | MUL                           { Mul $1 }
  | DIV                           { Div $1 }
  | MOD                           { Mod $1 }
  | EQ                            { Eq $1 }
  | GT                            { Gt $1 }
  | LT                            { Lt $1 }
  | LBRACE commandlist RBRACE     { ProcConst ($2, $1, $3) }
  | LBRACE RBRACE                 { ProcConst ([], $1, $2) }
  | COMMAND                       { getc $1 }
;
